 .386                   ;enable instructions
        .xmm                    ;enable instructions
        .model flat,c           ;use C naming convention (stdcall is default)

	include algo-types.inc
	include macros.inc
	extrn   printf:near

		.code

;void initQueue(struct queue* q, void* ary, unsigned int maxLen);
initQueue proc uses esi,
	q:ptr queue, ary:PTR dword, maxLen: dword

	mov esi, q
	mov (queue ptr [esi]).front, 0
	mov (queue ptr [esi]).rear, 0

	mov eax, ary
	mov (queue ptr [esi]).ary, eax
	mov eax, maxLen
	mov (queue ptr [esi]).len, eax

	ret
initQueue endp


;int queueEmpty(struct queue* q)
;return: eax = 1 if empty; 0 if not empty
queueEmpty proc uses ebx esi,
	q: ptr queue
	
	mov eax, 1
	mov esi, q
	mov ebx, (queue ptr [esi]).front
	cmp ebx, (queue ptr [esi]).rear
	;if(q->front == q->rear) empty
	je exitp
	mov eax, 0

exitp:
	ret
queueEmpty endp

;int queueFull(struct queue* q)
;return: eax = 1 if full; 0 if not full
;used ebx, esi
queueFull proc uses ebx esi,
	q: ptr queue

	mov esi, q
	mov ebx, (queue ptr [esi]).rear
	
	;if (((q->rear + 1) % q->len) == q->front), full
	inc ebx
	mov ax, bx ;ax = bx = rear + 1
	mov ebx, (queue ptr [esi]).len ;bl = len
	div bl ;ax / bl

	mov ebx, (queue ptr [esi]).front
	cmp ah, bh

	mov eax, 1
	je exitp
	mov eax, 0

exitp:
	ret
queueFull endp

;int enQueue(struct queue* q, unsigned int data)
;enqueue data
;return: eax = -1 if failed; 0 if OK
enQueue proc uses esi edi ebx,
	q: ptr queue, data: dword

	mov esi, q

	invoke queueFull, esi
	cmp eax, 1
	je exit_err ;queue is full

	;q->ary[q->rear] = data
	mov eax, (queue ptr[esi]).rear
	shl eax, 2 ;index = eax * 4
	mov edi, (queue ptr[esi]).ary
	add edi, eax ;edi = ary[rear]
	mov eax, data
	mov [edi], eax
	
	;q->rear = (q->rear + 1) % q->len;
	mov eax, (queue ptr[esi]).rear
	inc eax
	mov ebx, (queue ptr [esi]).len ;bl = len
	div bl ;ax / bl, AH = AX MODE BL
	mov byte ptr [(queue ptr[esi]).rear], ah
	mov eax, 0
	jmp exitp

exit_err:
	mov eax, -1
exitp:
	ret
enQueue endp

;int deQueue(struct queue* q, unsigned int *data)
;result is in data
;return: eax = -1 if failed; 0 if OK
deQueue proc uses ebx esi edi,
	q:ptr queue, pdata:PTR DWORD

	mov esi, q
	invoke queueEmpty, esi
	cmp eax, 1
	je exit_err ;queue is empty

	;*data = q->ary[q->front]
	mov eax, (queue ptr[esi]).front
	shl eax, 2 ;index = eax * 4
	mov edi, (queue ptr[esi]).ary
	add edi, eax ;edi = ary[rear]
	mov eax, [edi]

	mov ebx, pdata
	mov [ebx], eax

	;q->front = (q->front + 1) % q->len
	mov eax, (queue ptr[esi]).front
	inc eax
	mov ebx, (queue ptr [esi]).len ;bl = len
	div bl ;ax / bl, AH = AX MODE BL
	mov byte ptr [(queue ptr[esi]).front], ah
	mov eax, 0
	jmp exitp

exit_err:
	mov eax, -1

exitp:	
	ret
deQueue endp

		end 